package com.em.sugarfight.service.engine;

import com.em.sugarfight.controller.OperateController;
import com.em.sugarfight.entity.*;
import com.em.sugarfight.sugarEnums.Direction;
import com.em.sugarfight.sugarEnums.OwnershipEnum;
import com.em.sugarfight.sugarEnums.TargetType;
import com.em.sugarfight.sugarEnums.TeamEnum;
import com.em.sugarfight.util.CoordinateConverter;
import com.em.sugarfight.util.GameStateAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;

@Component
public class MovementDecisionEngine {

    private static final Logger logger = LoggerFactory.getLogger(MovementDecisionEngine.class);

    /**
     * 核心移动决策方法
     * @param gameState 当前游戏状态
     * @return 移动命令
     */
    public MoveCommand decideMovement(GameState gameState,DangerMap dangerMap) {
        logger.info("危险地图:{}",dangerMap);
        // 1. 危险评估 - 最高优先级
        Position currentPos = CoordinateConverter.pixelToGrid(gameState.getMy_player().getPosition());
        logger.info("当前位置:{}",currentPos);

        if (dangerMap.isInDanger(currentPos)) {
            // 紧急逃生
            Position safePosition = findNearestSafePosition(currentPos, dangerMap, gameState);
            if(safePosition != null) {
                logger.info("紧急逃生安全位置{}", safePosition);
                return generateMoveCommand(planPath(currentPos, safePosition, gameState, dangerMap), gameState, dangerMap);
            }
        }

        // 2. 目标选择
        Target bestTarget = selectBestTarget(gameState, dangerMap);
        logger.info("选择目标{}",bestTarget);

        // 3. 路径规划
        Path optimalPath = planPath(currentPos, bestTarget.getPosition(), gameState, dangerMap);
        logger.info("规划路径为:{}",optimalPath);

        // 4. 生成移动命令
        return generateMoveCommand(optimalPath, gameState,dangerMap);
    }

    /**
     * 寻找最近的安全位置
     */
    private Position findNearestSafePosition(Position start, DangerMap dangerMap, GameState gameState) {
        Queue<Position> queue = new LinkedList<>();
        Set<Position> visited = new HashSet<>();

        queue.offer(start);
        visited.add(start);

        while (!queue.isEmpty()) {
            Position current = queue.poll();
//            logger.info("寻找安全位置，当前位置:{}",current);

            if (isValidPosition(current,gameState) && !dangerMap.isInDanger(current) && !current.equals(start)) {
                return current; // 找到安全位置
            }

            // 搜索相邻位置
            for (Direction dir : Arrays.asList(Direction.U, Direction.D, Direction.L, Direction.R)) {
                Position next = current.move(dir);

                if (isValidPosition(next, gameState) && !visited.contains(next)) {
                    visited.add(next);
                    queue.offer(next);
                }
            }
        }

        return null; // 没找到安全位置
    }

    /**
     * 计算危险地图 - 标记所有危险区域
     */
    private DangerMap calculateDangerMap(GameState gameState) {
        DangerMap dangerMap = new DangerMap(gameState.getMapWidth(), gameState.getMapHeight());

        // 标记炸弹威胁区域
        for (Bomb bomb : gameState.getBombs()) {
            dangerMap.markBombDanger(bomb, gameState.getCurrent_tick());
        }

        // 标记敌人可能放炸弹的位置
        for (PlayerStateVo enemy : getEnemies(gameState)) {
            if (enemy.getBomb_pack_count() > 0) {
                dangerMap.markPotentialBombZones(enemy);
            }
        }

        return dangerMap;
    }

    /**
     * 紧急逃生算法
     */
    private MoveCommand findEmergencyEscape(GameState gameState, DangerMap dangerMap) {
        PixelPosition currPixelPos = gameState.getMy_player().getPosition();
        Position currentPos = CoordinateConverter.pixelToGrid(currPixelPos);
        List<Position> safePixelPositions = new ArrayList<>();

        // BFS搜索最近的安全位置
        Queue<Position> queue = new LinkedList<>();
        Set<Position> visited = new HashSet<>();

        queue.offer(currentPos);
        visited.add(currentPos);

        while (!queue.isEmpty()) {
            Position pos = queue.poll();

            // 检查四个方向
            for (Direction dir : Direction.values()) {
                Position nextPos = pos.move(dir);

                if (isValidPosition(nextPos, gameState) && !visited.contains(nextPos)) {
                    visited.add(nextPos);

                    if (!dangerMap.isInDanger(nextPos)) {
                        // 找到安全位置
                        return new MoveCommand(getDirectionTo(currentPos, nextPos).getValue(),false,0);
                    }
                    queue.offer(nextPos);
                }
            }
        }

        // 如果找不到完全安全的位置，选择威胁最小的
        return chooseLeastDangerousMove(gameState, dangerMap);
    }

    /**
     * 目标选择算法 - 根据当前局势选择最佳目标
     */
    private Target selectBestTarget(GameState gameState, DangerMap dangerMap) {
        List<Target> candidates = new ArrayList<>();

        // 1. 道具目标
        for (MapItem item : gameState.getMap_items()) {
            double value = evaluateItemValue(item, gameState);
            double risk = dangerMap.getRiskLevel(item.getPosition());
            candidates.add(new Target(item.getPosition(), value - risk, TargetType.ITEM));
        }

        // 2. 占领目标 - 寻找有价值的未占领格子
        for (Position pos : findStrategicPositions(gameState)) {
            OwnershipEnum ownership = gameState.getCell(pos).getOwnership();
            TeamEnum team = gameState.getMy_player().getTeam();

            if (!ownership.name().equals(team.name())) {
                double value = evaluateOccupationValue(pos, gameState);
                double risk = dangerMap.getRiskLevel(pos);
                candidates.add(new Target(pos, value - risk, TargetType.OCCUPATION));
            }
        }

        // 3. 攻击目标 - 接近敌人进行攻击
        for (PlayerStateVo enemy : getEnemies(gameState)) {
            double value = evaluateAttackValue(enemy, gameState);
            PixelPosition position = enemy.getPosition();
            Position gridPosition = CoordinateConverter.pixelToGrid(position);
            double risk = dangerMap.getRiskLevel(gridPosition);
            candidates.add(new Target(gridPosition, value - risk, TargetType.ATTACK));
        }

        // 选择评分最高的目标
        return candidates.stream()
                .max(Comparator.comparing(Target::getScore))
                .orElse(getDefaultTarget(gameState));
    }

    /**
     * A*路径规划算法
     */
    private Path planPath(Position start, Position goal, GameState gameState, DangerMap dangerMap) {
        logger.info("路径规划");
        PriorityQueue<PathNode> openSet = new PriorityQueue<>();
        Map<Position, PathNode> allNodes = new HashMap<>();

        PathNode startNode = new PathNode(start, 0, heuristic(start, goal));
        openSet.offer(startNode);
        allNodes.put(start, startNode);

        while (!openSet.isEmpty()) {
            PathNode current = openSet.poll();
//            logger.info("规划中,当前位置:{}",current.getPosition());

            if (current.getPosition().equals(goal)) {
                return reconstructPath(current);
            }

            for (Direction dir : Direction.values()) {
                if(Direction.N.equals(dir))
                    continue;
                Position nextPos = current.getPosition().move(dir);
//                logger.info("规划路径nextPos:{}",nextPos);

                if (!isValidPositionToPlanPath(nextPos, gameState)) continue;

                double moveCost = calculateMoveCost(current.getPosition(), nextPos, gameState, dangerMap);
                double newCost = current.getCost() + moveCost;

                PathNode nextNode = allNodes.get(nextPos);
                if (nextNode == null) {
                    nextNode = new PathNode(nextPos, newCost, heuristic(nextPos, goal));
                    nextNode.setParent(current);
                    allNodes.put(nextPos, nextNode);
                    openSet.offer(nextNode);
                } else if (newCost < nextNode.getCost()) {
                    nextNode.setCost(newCost);
                    nextNode.setParent(current);
                }
            }
        }

        return null; // 无法到达目标
    }

    /**
     * 评估移动成本 - 考虑地形、危险等因素
     */
    private double calculateMoveCost(Position from, Position to, GameState gameState, DangerMap dangerMap) {
        double baseCost = 1.0;

        Cell cell = gameState.getCell(to);

        // 地形影响
        switch (cell.getTerrain()) {
            case B: // 加速点
                baseCost *= 0.8;
                break;
            case M: // 减速点
                baseCost *= 1.5;
                break;
            case I:
            case N:
                return Double.MAX_VALUE; // 不可通过
            case D: // 可破坏障碍物
                baseCost *= 2.0;
                break;
        }

        // 危险惩罚
        double dangerLevel = dangerMap.getRiskLevel(to);
        baseCost += dangerLevel * 5.0;

        return baseCost;
    }

    /**
     * 生成最终的移动命令
     */
    private MoveCommand generateMoveCommand(Path path, GameState gameState, DangerMap dangerMap) {
        if (path == null || path.isEmpty()) {
            return new MoveCommand("N", false, 0); // 静止
        }

        Position currentPos = CoordinateConverter.pixelToGrid(gameState.getMy_player().getPosition());
        Position nextStep = path.getNextStep();
        Direction direction = getDirectionToNextStep(currentPos, nextStep);
        logger.info("next position terrain:{}",gameState.getCell(nextStep));

        // 根据情况决定移动步长
        int stride = calculateOptimalStride(gameState, dangerMap);
//        Cell[][] map = gameState.getMap();

//        if(map[nextStep.getY()][nextStep.getX()].getTerrain().name().equals("D"))
//            return new MoveCommand(direction.toString(), true, stride);
//        else
            return new MoveCommand(direction.toString(), false, stride);
    }

    // ============ 辅助方法实现 ============

    /**
     * 标记炸弹威胁区域
     */
//    private void markBombDanger(DangerMap dangerMap, Bomb bomb) {
//        dangerMap.markBombDanger(bomb);
//    }

    /**
     * 标记敌人潜在炸弹区域
     */
    private void markPotentialBombZones(DangerMap dangerMap, PlayerStateVo enemy) {
        dangerMap.markPotentialBombZones(enemy);
    }

    /**
     * 获取敌方玩家列表
     */
    private List<PlayerStateVo> getEnemies(GameState gameState) {
        List<PlayerStateVo> enemies = new ArrayList<>();
        String myTeam = gameState.getMy_player().getTeam().name();

        for (PlayerStateVo player : gameState.getOther_players()) {
            if (!player.getTeam().name().equals(myTeam)) {
                enemies.add(player);
            }
        }

        return enemies;
    }

    /**
     * 选择威胁最小的移动方向
     */
    private MoveCommand chooseLeastDangerousMove(GameState gameState, DangerMap dangerMap) {
        PixelPosition pixelPosition = gameState.getMy_player().getPosition();
        Position currentPos = CoordinateConverter.pixelToGrid(pixelPosition);
        Direction bestDirection = Direction.N;
        double minDanger = Double.MAX_VALUE;

        // 检查四个方向
        for (Direction dir : Arrays.asList(Direction.U, Direction.D, Direction.L, Direction.R)) {
            Position nextPos = currentPos.move(dir);

            if (isValidPosition(nextPos, gameState)) {
                double danger = dangerMap.getRiskLevel(nextPos);
                if (danger < minDanger) {
                    minDanger = danger;
                    bestDirection = dir;
                }
            }
        }

        return new MoveCommand(bestDirection.toString(), false, 0);
    }

    /**
     * 评估道具价值
     */
    private double evaluateItemValue(MapItem item, GameState gameState) {
        PlayerStateVo myPlayer = gameState.getMy_player();
        double baseValue = 0;

        switch (item.getType().name()) {
            case "BP": // 炸弹背包
                baseValue = 15.0;
                // 如果已经有很多炸弹包，价值递减
                if (myPlayer.getBomb_pack_count() > 2) {
                    baseValue *= 0.5;
                }
                break;
            case "SP": // 强化药水
                baseValue = 12.0;
                if (myPlayer.getSweet_potion_count() > 1) {
                    baseValue *= 0.7;
                }
                break;
            case "AB": // 灵巧飞靴
                baseValue = 10.0;
                if (myPlayer.getAgility_boots_count() > 1) {
                    baseValue *= 0.6;
                }
                break;
        }

        // 考虑距离因素
        Position myPos = CoordinateConverter.pixelToGrid(myPlayer.getPosition());
        int distance = myPos.manhattanDistance(item.getPosition());
        baseValue *= Math.max(0.1, 1.0 - distance * 0.1); // 距离越远价值越低

        return baseValue;
    }

    /**
     * 寻找战略位置
     */
    private List<Position> findStrategicPositions(GameState gameState) {
        List<Position> strategicPos = new ArrayList<>();
        Cell[][] map = gameState.getMap();

        for (int x = 0; x < map[0].length; x++) {
            for (int y = 0; y < map.length; y++) {
                Position pos = new Position(x, y);
                if (isStrategicPosition(pos, gameState)) {
                    strategicPos.add(pos);
                }
            }
        }

        return strategicPos;
    }

    /**
     * 判断是否为战略位置
     */
    private boolean isStrategicPosition(Position pos, GameState gameState) {
        Cell cell = gameState.getCell(pos);

        // 不能是障碍物
        if ("I".equals(cell.getTerrain().name()) || "N".equals(cell.getTerrain().name()) || "D".equals(cell.getTerrain().name())) {
            return false;
        }

        // 优先考虑：
        // 1. 加速点
//        if ("B".equals(cell.getTerrain().name())) return true;

        // 2. 地图边缘或角落（便于防守）
        Cell[][] map = gameState.getMap();
        int x = pos.getX(), y = pos.getY();
        if (x == 0 || x == map.length - 1 || y == 0 || y == map[0].length - 1) {
            return true;
        }

        // 3. 敌方占领区域附近（便于反击）
        String myTeam = gameState.getMy_player().getTeam().name();
        for (int dx = -2; dx <= 2; dx++) {
            for (int dy = -2; dy <= 2; dy++) {
                Position nearbyPos = new Position(x + dx, y + dy);
                if (isValidPosition(nearbyPos, gameState)) {
                    Cell nearbyCell = gameState.getCell(nearbyPos);
                    if (!nearbyCell.getOwnership().name().equals(myTeam)) {
                        return true;
                    }
                }
            }
        }

        return false;
    }

    /**
     * 评估占领价值
     */
    private double evaluateOccupationValue(Position pos, GameState gameState) {
        double value = 15.0; // 基础占领价值
        Cell cell = gameState.getCell(pos);

        // 地形加成
        switch (cell.getTerrain().name()) {
            case "B": // 加速点
                value += 10.0;
                break;
            case "M": // 减速点
                value -= 2.0;
                break;
        }

        // 位置价值
        Cell[][] map = gameState.getMap();
        int x = pos.getX(), y = pos.getY();

        // 边缘位置价值更高（易守难攻）
        if (x == 0 || x == map.length - 1 || y == 0 || y == map[0].length - 1) {
            value += 3.0;
        }

        // 中心位置也有价值（控制力强）
        int centerX = map.length / 2, centerY = map[0].length / 2;
        int distanceFromCenter = Math.abs(x - centerX) + Math.abs(y - centerY);
        if (distanceFromCenter <= 2) {
            value += 2.0;
        }

        // 连片奖励 - 与己方占领区域相邻
        String myTeam = gameState.getMy_player().getTeam().name();
        int adjacentCount = 0;
        for (Direction dir : Arrays.asList(Direction.U, Direction.D, Direction.L, Direction.R)) {
            Position adjPos = pos.move(dir);
            if (isValidPosition(adjPos, gameState)) {
                Cell adjCell = gameState.getCell(adjPos);
                if (myTeam.equals(adjCell.getOwnership().name())) {
                    adjacentCount++;
                }
            }
        }
        value += adjacentCount * 2.0; // 每个相邻己方格子+2分

        return value;
    }

    /**
     * 评估攻击价值
     */
    private double evaluateAttackValue(PlayerStateVo enemy, GameState gameState) {
        double value = 5.0; // 基础攻击价值

        // 敌人血量越少，攻击价值越高
        if ("D".equals(enemy.getStatus().name())) { // 炸晕状态
            value += 8.0; // 优先攻击晕眩敌人
        }

        // 敌人道具越多，攻击价值越高
        int enemyItemCount = enemy.getBomb_pack_count() + enemy.getSweet_potion_count() + enemy.getAgility_boots_count();
        value += enemyItemCount * 2.0;

        // 如果己方有炸弹包，攻击价值提升
        PlayerStateVo myPlayer = gameState.getMy_player();
        if (myPlayer.getBomb_pack_count() > 0) {
            value += 5.0;
        }

        return value;
    }

    /**
     * 获取默认目标
     */
    private Target getDefaultTarget(GameState gameState) {
        // 默认目标：向地图中心移动
        Cell[][] map = gameState.getMap();
        Position centerPos = new Position(map.length / 2, map[0].length / 2);
        return new Target(centerPos, 1.0, TargetType.OCCUPATION);
    }

    /**
     * A*算法的启发式函数（曼哈顿距离）
     */
    private double heuristic(Position from, Position to) {
        return from.manhattanDistance(to);
    }

    /**
     * 重建路径
     */
    private Path reconstructPath(PathNode endNode) {
        return Path.reconstructFrom(endNode);
    }

    /**
     * 检查位置是否有效
     */
    private boolean isValidPosition(Position pos, GameState gameState) {
        Cell[][] map = gameState.getMap();
        int x = pos.getY(), y = pos.getX();

        // 边界检查
        if (x < 0 || x >= map.length || y < 0 || y >= map[0].length) {
            return false;
        }

        // 地形检查
        Cell cell = map[x][y];
        String terrain = cell.getTerrain().name();
        return !"I".equals(terrain) && !"N".equals(terrain) && !"D".equals(terrain);
    }

    private boolean isValidPositionToPlanPath(Position pos, GameState gameState) {
        Cell[][] map = gameState.getMap();
        int x = pos.getY(), y = pos.getX();

        // 边界检查
        if (x < 0 || x >= map.length || y < 0 || y >= map[0].length) {
            return false;
        }

        // 地形检查
        Cell cell = map[x][y];
        String terrain = cell.getTerrain().name();
        return !"I".equals(terrain) && !"N".equals(terrain);
    }

    /**
     * 计算从当前位置到目标位置的方向
     */
    private Direction getDirectionTo(Position from, Position to) {
        int dx = to.getX() - from.getX();
        int dy = to.getY() - from.getY();

        if (Math.abs(dx) > Math.abs(dy)) {
            return dx > 0 ? Direction.R : Direction.L;
        } else if (dy != 0) {
            return dy > 0 ? Direction.D : Direction.U;
        }

        return Direction.N;
    }

    /**
     * 获取到下一步的方向 - 改进版本
     */
    private Direction getDirectionToNextStep(Position currentPos, Position nextStep) {
        logger.info("currentPos:{}",currentPos);
        logger.info("nextStep:{}",nextStep);
        int dx = nextStep.getX() - currentPos.getX();
        int dy = nextStep.getY() - currentPos.getY();

        if (Math.abs(dx) > Math.abs(dy)) {
            return dx > 0 ? Direction.R : Direction.L;
        } else if (dy != 0) {
            return dy > 0 ? Direction.U : Direction.D;
        }

        return Direction.N;
    }

    /**
     * 计算最优移动步长
     */
    private int calculateOptimalStride(GameState gameState, DangerMap dangerMap) {
        PlayerStateVo myPlayer = gameState.getMy_player();
        Position currentPos = CoordinateConverter.pixelToGrid(myPlayer.getPosition());

        // 基础移动速度（根据游戏设定调整）
        int baseSpeed = 100;

        // 如果处于危险中，使用最大步长快速逃离
        if (dangerMap.isInDanger(currentPos)) {
            return 0; // 使用默认最大速度
        }

        // 检查是否有灵巧飞靴加速效果
        boolean hasSpeedBoost = myPlayer.getExtra_status().stream()
                .anyMatch(status -> "LIT".equals(status.getName().name())); // 闪电状态

        if (hasSpeedBoost) {
            return 0; // 使用最大速度
        }

        // 精细控制：接近目标时减速
        return baseSpeed / 2; // 使用2/3速度，便于精确定位
    }

//    // ============ 新增：游戏状态管理接口 ============
//
//    /**
//     * 主要决策入口 - 整合所有算法
//     */
//    public MoveCommand makeDecision(GameState gameState) {
//        try {
//            return decideMovement(gameState,null);
//        } catch (Exception e) {
//            // 异常处理：返回安全的默认命令
//            System.err.println("决策异常: " + e.getMessage());
//            return new MoveCommand("N", false, 0);
//        }
//    }

    /**
     * 调试信息输出
     */
    public void printDebugInfo(GameState gameState) {
        System.out.println("=== 决策调试信息 ===");
        System.out.println("当前Tick: " + gameState.getCurrent_tick());
        System.out.println("我的位置: " + gameState.getMy_player().getPosition());
        System.out.println("我的状态: " + gameState.getMy_player().getStatus());
        System.out.println("道具数量: B=" + gameState.getMy_player().getBomb_pack_count() +
                ", S=" + gameState.getMy_player().getSweet_potion_count() +
                ", A=" + gameState.getMy_player().getAgility_boots_count());

        // 危险评估
        DangerMap dangerMap = calculateDangerMap(gameState);
        Position myPos = CoordinateConverter.pixelToGrid(gameState.getMy_player().getPosition());
        System.out.println("当前位置危险度: " + dangerMap.getRiskLevel(myPos));

        // 目标信息
        Target bestTarget = selectBestTarget(gameState, dangerMap);
        System.out.println("最佳目标: " + bestTarget);
        System.out.println("==================");
    }
}
